package com.ifacebox.face.track.sevice;

import com.arcsoft.face.*;
import com.arcsoft.face.enums.CompareModel;
import com.arcsoft.face.enums.DetectMode;
import com.arcsoft.face.enums.DetectOrient;
import com.arcsoft.face.enums.ErrorInfo;
import com.arcsoft.face.toolkit.ImageInfo;
import com.ifacebox.face.track.model.FaceConfig;

import java.util.ArrayList;
import java.util.List;

/**
 * @author znn
 */
public class FaceEngineService {
    public static final float FACE_THRESHOLD = 80.00f;
    public static final String APP_ID = "8vmbTH4xipgmk8QSzbJn2hfoG1j2FsCfBu6buqswJBLw";
    public static final String SDK_KEY = "6Az1wbQ8SRtxz7owKFH7VtSe51eBVuCerbEpgMfvQDAz";
    private final FaceEngine faceEngine;
    private final FaceConfigService faceConfigService;

    public FaceEngineService() {
        this.faceEngine = new FaceEngine();
        this.faceConfigService = new FaceConfigService();
    }

    public ActiveFileInfo sdkInit(DetectMode detectMode) throws Exception {
        FaceConfig faceConfig = this.faceConfigService.readConfig();
        int mok = this.faceEngine.activeOnline(faceConfig.getAppId(), faceConfig.getSdkKey());
        if (ErrorInfo.MOK.getValue() != mok && ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue() != mok) {
            throw new Exception(String.format("激活人脸引擎失败！(%d:%s)", mok, ErrorInfo.getValidEnum(mok).toString()));
        }
        mok = this.faceEngine.init(EngineConfiguration.builder().detectMode(detectMode).detectFaceMaxNum(10).detectFaceScaleVal(DetectMode.ASF_DETECT_MODE_VIDEO == detectMode ? 16 : 32).detectFaceOrientPriority(DetectOrient.ASF_OP_0_ONLY).functionConfiguration(FunctionConfiguration.builder().supportFaceDetect(true).supportFaceRecognition(true).supportAge(false).supportGender(false).supportFace3dAngle(false).supportLiveness(false).supportIRLiveness(false).build()).build());
        if (ErrorInfo.MOK.getValue() != mok) {
            throw new Exception(String.format("初始化人脸引擎失败！(%d:%s)", mok, ErrorInfo.getValidEnum(mok).toString()));
        }
        ActiveFileInfo activeFileInfo = new ActiveFileInfo();
        mok = this.faceEngine.getActiveFileInfo(activeFileInfo);
        if (ErrorInfo.MOK.getValue() != mok) {
            throw new Exception(String.format("获取激活文件信息失败！(%d:%s)", mok, ErrorInfo.getValidEnum(mok).toString()));
        }
        return activeFileInfo;
    }

    public void sdkDestroy() {
        this.faceEngine.unInit();
    }

    public List<FaceInfo> faceDetect(ImageInfo imageInfo) throws Exception {
        List<FaceInfo> faceInfoList = new ArrayList<>();
        int mok = this.faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
        if (ErrorInfo.MOK.getValue() != mok) {
            throw new Exception(String.format("人脸检测失败！(%d:%s)", mok, ErrorInfo.getValidEnum(mok).toString()));
        }
        if (faceInfoList.isEmpty()) {
            throw new Exception("未检测到人脸！");
        }
        return faceInfoList;
    }

    public FaceFeature faceFeature(ImageInfo imageInfo, FaceInfo faceInfo) throws Exception {
        FaceFeature faceFeature = new FaceFeature();
        int mok = this.faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfo, faceFeature);
        if (ErrorInfo.MOK.getValue() != mok) {
            throw new Exception(String.format("提取人脸特征失败！(%d:%s)", mok, ErrorInfo.getValidEnum(mok).toString()));
        }
        return faceFeature;
    }

    public float faceCompare(byte[] featureData1, byte[] featureData2) throws Exception {
        return this.faceCompare(new FaceFeature(featureData1), new FaceFeature(featureData2));
    }

    public float faceCompare(FaceFeature faceFeature1, FaceFeature faceFeature2) throws Exception {
        FaceSimilar faceSimilar = new FaceSimilar();
        int mok = this.faceEngine.compareFaceFeature(faceFeature1, faceFeature2, CompareModel.ID_PHOTO, faceSimilar);
        if (ErrorInfo.MOK.getValue() != mok) {
            throw new Exception(String.format("人脸比对失败！(%d:%s)", mok, ErrorInfo.getValidEnum(mok).toString()));
        }
        return faceSimilar.getScore() * 100;
    }
}
